package org.dandsoft.blackbox.observer;

import org.dandsoft.blackbox.utils.BinaryTree;
import org.dandsoft.blackbox.Signal;
import org.dandsoft.blackbox.SignalId;

/**
 * @author Vilyuzhanin Denis (Fin)
 */
public class SynchronousSignals<Value> {
    private BinaryTree<Entry> tree;
    private final Object lock = new Object();

    public SynchronousSignals() {
        this.tree = new BinaryTree<Entry>();
    }

    public void notify(Signal signal1, Signal signal2) {
        Entry entry = findEntry(signal1.getSignalId(), signal2.getSignalId(), true);
        entry.counter++;
    }

    

    /**
     * Производит поиск в дереве по хешу.
     *
     * @param id1
     * @param id2
     * @param isCreate
     * @return
     */
    protected Entry findEntry(SignalId id1, SignalId id2, boolean isCreate) {
        long hash = makeHash(id1, id2);
        Entry first = tree.get(hash);
        Entry entry = first;
        for (; entry != null; entry = entry.next) {
            if (entry.id1.equals(id1) && entry.id2.equals(id2)) {
                return entry;
            }
        }
        if (isCreate) {
            synchronized (lock) {
                Entry newEntry = new Entry();
                newEntry.id1 = id1;
                newEntry.id2 = id2;
                if (first == null) {
                    tree.put(hash, newEntry);
                } else {
                    newEntry.next = first.next;
                    first.next = newEntry.next;

                }
                return newEntry;
            }
        }
        return null;
    }

    static long makeHash(SignalId id1, SignalId id2) {
        return id1.getValue() << 16 + id2.getValue();
    }

    static class Entry {
        public Entry next;
        public int counter;
        public SignalId id1;
        public SignalId id2;
        public Object value;
    }
}
